tools/xsm: Expose Flask XSM AVC functions to user-space
authorKeir Fraser <keir.fraser@citrix.com>
Tue, 26 Jan 2010 07:50:04 +0000 (07:50 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Tue, 26 Jan 2010 07:50:04 +0000 (07:50 +0000)
This patch exposes the flask_access, flask_avc_cachestats,
flask_avc_hashstats, flask_getavc_threshold, flask_setavc_threshold,
and flask_policyvers functions to user-space. A python wrapper was
created for the flask_access function to facilitate policy based
user-space access control decisions. flask.h was renamed to libflask.h
to remove a naming conflict.

Signed-off-by : Machon Gregory <mbgrego@tycho.ncsc.mil>

tools/flask/libflask/Makefile
tools/flask/libflask/flask_op.c
tools/flask/libflask/include/flask.h [deleted file]
tools/flask/libflask/include/libflask.h [new file with mode: 0644]
tools/flask/utils/getenforce.c
tools/flask/utils/loadpolicy.c
tools/flask/utils/setenforce.c
tools/python/xen/lowlevel/flask/flask.c

index c03fc8aca84b0b57660a1745f828cbf949a27e62..7f33f124df85c5a90b6a4217e40701bbe3710a4a 100644 (file)
@@ -38,7 +38,7 @@ install: build
        $(INSTALL_DATA) libflask.a $(DESTDIR)$(LIBDIR)
        ln -sf libflask.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)/libflask.so.$(MAJOR)
        ln -sf libflask.so.$(MAJOR) $(DESTDIR)$(LIBDIR)/libflask.so
-       $(INSTALL_DATA) include/flask.h $(DESTDIR)$(INCLUDEDIR)
+       $(INSTALL_DATA) include/libflask.h $(DESTDIR)$(INCLUDEDIR)/xen/xsm
 
 .PHONY: TAGS
 TAGS:
index 8b40c7059585c9aafc40df130a32fc4056e5883e..29c3cd1149095c7d8fcda3f8c7e94769f35e4996 100644 (file)
@@ -19,7 +19,7 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <sys/ioctl.h>
-#include <flask.h>
+#include <libflask.h>
 #include <xenctrl.h>
 
 int flask_load(int xc_handle, char *buf, uint32_t size)
@@ -342,3 +342,160 @@ int flask_del_device(int xc_handle, unsigned long device)
     return 0;
 
 }
+
+int flask_access(int xc_handle, const char *scon, const char *tcon,
+                u_int16_t tclass, u_int32_t req,
+                u_int32_t *allowed, u_int32_t *decided,
+                u_int32_t *auditallow, u_int32_t *auditdeny,
+                u_int32_t *seqno)
+{
+/* maximum number of digits in a 16-bit decimal number: */
+#define MAX_SHORT_DEC_LEN 5
+
+    char *buf;
+    int bufLen;
+    int err;
+    flask_op_t op;
+    u_int32_t dummy_allowed;
+    u_int32_t dummy_decided;
+    u_int32_t dummy_auditallow;
+    u_int32_t dummy_auditdeny;
+    u_int32_t dummy_seqno;
+  
+    if (!allowed)
+        allowed = &dummy_allowed;
+    if (!decided)
+        decided = &dummy_decided;
+    if (!auditallow)
+        auditallow = &dummy_auditallow;
+    if (!auditdeny)
+        auditdeny = &dummy_auditdeny;
+    if (!seqno)
+        seqno = &dummy_seqno;
+
+    if (!scon)
+        return -EINVAL;
+    if (!tcon)
+        return -EINVAL;
+
+    bufLen = strlen(scon) + 1 + strlen(tcon) + 1 +
+        MAX_SHORT_DEC_LEN + 1 +
+        sizeof(req)*2 + 1;
+    buf = malloc(bufLen);
+    snprintf(buf, bufLen, "%s %s %hu %x", scon, tcon, tclass, req);
+
+    op.cmd = FLASK_ACCESS;
+    op.buf = buf;
+    op.size = strlen(buf)+1;
+    
+    if ( (err = xc_flask_op(xc_handle, &op)) != 0 )
+    {
+        free(buf);
+        return err;
+    }
+   
+    if (sscanf(op.buf, "%x %x %x %x %u",
+               allowed, decided,
+               auditallow, auditdeny,
+               seqno) != 5) {
+        err = -EILSEQ;
+    }
+
+    err = ((*allowed & req) == req)? 0 : -EPERM;
+
+    return err;
+
+}
+
+int flask_avc_hashstats(int xc_handle, char *buf, int size)
+{
+    int err;
+    flask_op_t op;
+  
+    op.cmd = FLASK_AVC_HASHSTATS;
+    op.buf = buf;
+    op.size = size;
+  
+    if ( (err = xc_flask_op(xc_handle, &op)) != 0 )
+    {
+        free(buf);
+        return err;
+    }
+
+    return 0;
+}
+
+int flask_avc_cachestats(int xc_handle, char *buf, int size)
+{
+    int err;
+    flask_op_t op;
+  
+    op.cmd = FLASK_AVC_CACHESTATS;
+    op.buf = buf;
+    op.size = size;
+  
+    if ( (err = xc_flask_op(xc_handle, &op)) != 0 )
+    {
+        free(buf);
+        return err;
+    }
+
+    return 0;
+}
+
+int flask_policyvers(int xc_handle, char *buf, int size)
+{
+    int err;
+    flask_op_t op;
+  
+    op.cmd = FLASK_POLICYVERS;
+    op.buf = buf;
+    op.size = size;
+
+    if ( (err = xc_flask_op(xc_handle, &op)) != 0 )
+    {
+        free(buf);
+        return err;
+    }
+
+    return 0;
+}
+
+int flask_getavc_threshold(int xc_handle)
+{
+    int err;
+    flask_op_t op;
+    char buf[20];            
+    int size = 20;
+    int threshold;
+    op.cmd = FLASK_GETAVC_THRESHOLD;
+    op.buf = buf;
+    op.size = size;
+    
+    if ( (err = xc_flask_op(xc_handle, &op)) != 0 )
+        return err;
+
+    sscanf(buf, "%i", &threshold);
+
+    return threshold;
+}
+
+int flask_setavc_threshold(int xc_handle, int threshold)
+{
+    int err;
+    flask_op_t op;
+    char buf[20];            
+    int size = 20;
+    op.cmd = FLASK_SETAVC_THRESHOLD;
+    op.buf = buf;
+    op.size = size;
+
+    snprintf(buf, size, "%i", threshold);
+    if ( (err = xc_flask_op(xc_handle, &op)) != 0 )
+        return err;
+
+    return 0;
+}
diff --git a/tools/flask/libflask/include/flask.h b/tools/flask/libflask/include/flask.h
deleted file mode 100644 (file)
index 44de26b..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- *
- *  Authors:  Michael LeMay, <mdlemay@epoch.ncsc.mil>
- *            George Coker, <gscoker@alpha.ncsc.mil>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2,
- *  as published by the Free Software Foundation.
- */
-
-#ifndef __FLASK_H__
-#define __FLASK_H__
-
-#include <stdint.h>
-#include <xen/xen.h>
-#include <xen/xsm/flask_op.h>
-
-int flask_load(int xc_handle, char *buf, uint32_t size);
-int flask_context_to_sid(int xc_handle, char *buf, uint32_t size, uint32_t *sid);
-int flask_sid_to_context(int xc_handle, int sid, char *buf, uint32_t size);
-int flask_getenforce(int xc_handle);
-int flask_setenforce(int xc_handle, int mode);
-int flask_add_pirq(int xc_handle, unsigned int pirq, char *scontext);
-int flask_add_ioport(int xc_handle, unsigned long low, unsigned long high,
-                      char *scontext);
-int flask_add_iomem(int xc_handle, unsigned long low, unsigned long high,
-                     char *scontext);
-int flask_add_device(int xc_handle, unsigned long device, char *scontext);
-int flask_del_pirq(int xc_handle, unsigned int pirq);
-int flask_del_ioport(int xc_handle, unsigned long low, unsigned long high);
-int flask_del_iomem(int xc_handle, unsigned long low, unsigned long high);
-int flask_del_device(int xc_handle, unsigned long device);
-#define flask_add_single_ioport(x, l, s) flask_add_ioport(x, l, l, s)
-#define flask_add_single_iomem(x, l, s) flask_add_iomem(x, l, l, s)
-#define flask_del_single_ioport(x, l) flask_del_ioport(x, l, l)
-#define flask_del_single_iomem(x, l) flask_del_iomem(x, l, l);
-
-#define OCON_PIRQ_STR   "pirq"
-#define OCON_IOPORT_STR "ioport"
-#define OCON_IOMEM_STR  "iomem"
-#define OCON_DEVICE_STR "pcidevice"
-#define INITCONTEXTLEN  256
-#endif /* __FLASK_H__ */
diff --git a/tools/flask/libflask/include/libflask.h b/tools/flask/libflask/include/libflask.h
new file mode 100644 (file)
index 0000000..7548d4e
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *
+ *  Authors:  Michael LeMay, <mdlemay@epoch.ncsc.mil>
+ *            George Coker, <gscoker@alpha.ncsc.mil>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2,
+ *  as published by the Free Software Foundation.
+ */
+
+#ifndef __LIBFLASK_H__
+#define __LIBFLASK_H__
+
+#include <stdint.h>
+#include <xen/xen.h>
+#include <xen/xsm/flask_op.h>
+
+int flask_load(int xc_handle, char *buf, uint32_t size);
+int flask_context_to_sid(int xc_handle, char *buf, uint32_t size, uint32_t *sid);
+int flask_sid_to_context(int xc_handle, int sid, char *buf, uint32_t size);
+int flask_getenforce(int xc_handle);
+int flask_setenforce(int xc_handle, int mode);
+int flask_add_pirq(int xc_handle, unsigned int pirq, char *scontext);
+int flask_add_ioport(int xc_handle, unsigned long low, unsigned long high,
+                      char *scontext);
+int flask_add_iomem(int xc_handle, unsigned long low, unsigned long high,
+                     char *scontext);
+int flask_add_device(int xc_handle, unsigned long device, char *scontext);
+int flask_del_pirq(int xc_handle, unsigned int pirq);
+int flask_del_ioport(int xc_handle, unsigned long low, unsigned long high);
+int flask_del_iomem(int xc_handle, unsigned long low, unsigned long high);
+int flask_del_device(int xc_handle, unsigned long device);
+int flask_access(int xc_handle, const char *scon, const char *tcon,
+                  u_int16_t tclass, u_int32_t req,
+                  u_int32_t *allowed, u_int32_t *decided,
+                  u_int32_t *auditallow, u_int32_t *auditdeny,
+                  u_int32_t *seqno);
+int flask_avc_cachestats(int xc_handle, char *buf, int size);
+int flask_policyvers(int xc_handle, char *buf, int size);
+int flask_avc_hashstats(int xc_handle, char *buf, int size);
+int flask_getavc_threshold(int xc_handle);
+int flask_setavc_threshold(int xc_handle, int threshold);
+#define flask_add_single_ioport(x, l, s) flask_add_ioport(x, l, l, s)
+#define flask_add_single_iomem(x, l, s) flask_add_iomem(x, l, l, s)
+#define flask_del_single_ioport(x, l) flask_del_ioport(x, l, l)
+#define flask_del_single_iomem(x, l) flask_del_iomem(x, l, l);
+
+#define OCON_PIRQ_STR   "pirq"
+#define OCON_IOPORT_STR "ioport"
+#define OCON_IOMEM_STR  "iomem"
+#define OCON_DEVICE_STR "pcidevice"
+#define INITCONTEXTLEN  256
+#endif /* __LIBFLASK_H__ */
index 9960434ac8a6ae5cd93fac67f4eb0c2697b04cd4..1706f6a2e29a8bc49ca81a10a72d79ccb1f91610 100644 (file)
@@ -16,7 +16,7 @@
 #include <sys/stat.h>
 #include <string.h>
 #include <unistd.h>
-#include <flask.h>
+#include <libflask.h>
 
 static void usage (int argCnt, const char *args[])
 {
index bb6eeb8de54aad5027a47a084d39e9d4e91bfc0a..13e4cb2c3274b27af2557713429fb14a84cc49c8 100644 (file)
@@ -17,7 +17,7 @@
 #include <sys/stat.h>
 #include <string.h>
 #include <unistd.h>
-#include <flask.h>
+#include <libflask.h>
 
 #define USE_MMAP
 
index 91fb3594aaff5930d4d73947f3608a6cb51041d4..60e8eb086f1c70426b060b668fff9a3a2cd3ca7e 100644 (file)
@@ -16,7 +16,7 @@
 #include <sys/stat.h>
 #include <string.h>
 #include <unistd.h>
-#include <flask.h>
+#include <libflask.h>
 
 static void usage (int argCnt, const char *args[])
 {
index bb42b5ce8f9d1154636375717e4ceb5217e885a6..858d8d3b25552b0f77a81d881fd208e645f5f56b 100644 (file)
@@ -12,7 +12,7 @@
 
 #include <Python.h>
 #include <xenctrl.h>
-#include <flask.h>
+#include <libflask.h>
 
 #define PKG "xen.lowlevel.flask"
 #define CLS "flask"
@@ -190,6 +190,44 @@ static PyObject *pyflask_setenforce(PyObject *self, PyObject *args,
     return Py_BuildValue("i", ret);
 }
 
+static PyObject *pyflask_access(PyObject *self, PyObject *args,
+                                                       PyObject *kwds)
+{
+    int xc_handle;
+    char *tcon, *scon;
+    uint16_t tclass;
+    uint32_t req, allowed, decided, auditallow, auditdeny, seqno;
+    int ret;
+
+    static char *kwd_list[] = { "src_context", "tar_context", 
+                                "tar_class", "req_permissions",
+                                "decided", "auditallow","auditdeny",
+                                "seqno", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ssil|llll", kwd_list,
+                                      &scon, &tcon, &tclass, &req, &decided,
+                                      &auditallow, &auditdeny, &seqno) )
+        return NULL;
+
+    xc_handle = xc_interface_open();
+    if (xc_handle < 0) {
+        errno = xc_handle;
+        return PyErr_SetFromErrno(xc_error_obj);
+    }
+    
+    ret = flask_access(xc_handle, scon, tcon, tclass, req, &allowed, &decided,
+                        &auditallow, &auditdeny, &seqno);
+        
+    xc_interface_close(xc_handle);
+
+    if ( ret != 0 ) {
+        errno = -ret;
+        return PyErr_SetFromErrno(xc_error_obj);
+    }
+
+    return Py_BuildValue("i",ret);
+}
+
 static PyMethodDef pyflask_methods[] = {
     { "flask_context_to_sid",
       (PyCFunction)pyflask_context_to_sid,
@@ -224,7 +262,27 @@ static PyMethodDef pyflask_methods[] = {
       "Modifies the current mode for the Flask XSM module.\n"
       " mode [int]: mode to change to\n"
       "Returns: [int]: 0 on success; -1 on failure.\n" }, 
+
+    { "flask_access",
+      (PyCFunction)pyflask_access,
+      METH_KEYWORDS, "\n"
+      "Returns whether a source context has access to target context based on \
+       class and permissions requested.\n"
+      " scon [str]: source context\n"
+      " tcon [str]: target context\n"
+      " tclass [int]: target security class\n"
+      " req [int] requested permissions\n"
+      " allowed [int] permissions allow for the target class between the source \
+        and target context\n"
+      " decided [int] the permissions that were returned in the allowed \
+        parameter\n"
+      " auditallow [int] permissions set to audit on allow\n"
+      " auditdeny [int] permissions set to audit on deny\n"
+      " seqno [int] not used\n"
+      "Returns: [int]: 0 on all permission granted; -1 if any permissions are \
+       denied\n" }, 
     { NULL, NULL, 0, NULL }
+
 };
 
 PyMODINIT_FUNC initflask(void)